home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / stars / stars.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  20KB  |  700 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  *  Copyright (c) 1991, 1992, 1993 Ronald Joe Record                           *
  4.  *                                                                       *
  5.  *  All rights reserved. No part of this program or publication may be   *
  6.  *  reproduced, transmitted, transcribed, stored in a retrieval system,  *
  7.  *  or translated into any language or computer language, in any form or *
  8.  *  by any means, electronic, mechanical, magnetic, optical, chemical,   *
  9.  *  biological, or otherwise, without the prior written permission of:   *
  10.  *                                                                       *
  11.  *      Ronald Joe Record (408) 458-3718                                 *
  12.  *      212 Owen St., Santa Cruz, California 95062 USA                   *
  13.  *                                                                       *
  14.  *************************************************************************/
  15.  
  16. /* Written by Ron Record (rr@sco) 09 June 1991 */
  17.  
  18. #include "stars.h"
  19.  
  20. main(ac, av)
  21.     int ac;
  22.     char **av;
  23. {
  24.     Widget toplevel;
  25.     static int i;
  26.     unsigned char wname[256];
  27.     Arg wargs[1];
  28.     static XtResource resource[] = {
  29.     { "appDefaultsFileInstalled" , "AppDefaultsFileInstalled", XtRBoolean,
  30.         sizeof(Boolean), 0, XtRString, "False" } };
  31.  
  32.     parseargs(ac, av);
  33.     toplevel = XtInitialize(av[0], "Stars", NULL, 0, &ac, av);
  34.     framework = XtCreateManagedWidget("framework", 
  35.                          xmFormWidgetClass, toplevel, NULL, 0);
  36.     /*
  37.      * Create the canvas widget to display the star portal 
  38.      */
  39.     canvas = XtCreateManagedWidget("drawing_canvas", 
  40.                    xmDrawingAreaWidgetClass, framework, NULL, 0);
  41.         dpy = XtDisplay(canvas);
  42.         screen = XtScreen(canvas);
  43.     if (FullScreen) {
  44.             width = XDisplayWidth(dpy, DefaultScreen(dpy));
  45.             height = XDisplayHeight(dpy, DefaultScreen(dpy));
  46.     }
  47.     /* 
  48.      * Create the pushbutton widgets. 
  49.      */ 
  50.     button[0] =  XtCreateManagedWidget("go_button",
  51.                                 xmPushButtonWidgetClass,
  52.                                 framework, NULL, 0);
  53.     button[1] =  XtCreateManagedWidget("stop_button",
  54.                                 xmPushButtonWidgetClass,
  55.                                 framework, NULL, 0);
  56.     button[2] =  XtCreateManagedWidget("quit_button",
  57.                                 xmPushButtonWidgetClass,
  58.                                 framework, NULL, 0);
  59.     button[3] =  XtCreateManagedWidget("warp_button",
  60.                                 xmPushButtonWidgetClass,
  61.                                 framework, NULL, 0);
  62.     init_data();
  63.     init_canvas();
  64.     x_center = width / 2;
  65.     y_center = height / 2;
  66.     if (xflag)
  67.         midpt.x = x_center;
  68.     if (yflag)
  69.         midpt.y = y_center;
  70.     initsky();
  71.     srand((int)time(0));
  72.     if (Fflag)
  73.         for (i=0; i<=numcolors; i++)
  74.         XSetFillStyle(dpy, Data[i]->gc, FillTiled);
  75.     if (fflag)
  76.         for (i=0; i<=numcolors; i++)
  77.         XSetFunction(dpy, Data[i]->gc, write_mode);
  78.     /*  
  79.      * Add callbacks. 
  80.      */ 
  81.     XtAddCallback(button[0],XmNactivateCallback,start_iterate,NULL);
  82.     XtAddCallback(button[1],XmNactivateCallback,stop_iterate,NULL);
  83.     XtAddCallback(button[2], XmNactivateCallback, quit, NULL);
  84.     XtAddCallback(button[3], XmNactivateCallback, Warp, NULL);
  85.     XtRealizeWidget(toplevel);
  86.     /* Title */
  87.     sprintf((char *) wname, "Stars by Ron Record");
  88.      XChangeProperty(dpy, XtWindow(toplevel), XA_WM_NAME, XA_STRING, 8, 
  89.          PropModeReplace, wname, strlen(wname));
  90.     if (NoShowButtons) {
  91.         for (i=0;i<4;i++)
  92.             XtUnrealizeWidget(button[i]);
  93.         XtSetArg(wargs[0], XmNbottomPosition, &bottom);
  94.         XtGetValues(canvas, wargs, 1);
  95.         XtSetArg(wargs[0], XmNbottomPosition, 99);
  96.         XtSetValues(canvas, wargs, 1);
  97.     }
  98.     XtAddCallback(canvas, XmNresizeCallback, resize, Data); 
  99.     XtAddEventHandler(canvas, KeyPressMask,
  100.              FALSE, Getkey, NULL);
  101.     XtAddEventHandler(button[0], KeyPressMask,
  102.              FALSE, Getkey, NULL);
  103.     XtAddEventHandler(button[1], KeyPressMask,
  104.              FALSE, Getkey, NULL);
  105.     XtAddEventHandler(button[2], KeyPressMask,
  106.              FALSE, Getkey, NULL);
  107.     XtAddEventHandler(button[3], KeyPressMask,
  108.              FALSE, Getkey, NULL);
  109.     Clear();
  110.     if (icflag)
  111.         initcolor = WhitePixelOfScreen(screen);
  112.       work_proc_id = XtAddWorkProc(mvstars, canvas);
  113.     XtGetApplicationResources(toplevel, &appDefaultsFileInstalled, resource,
  114.             1, NULL, 0);
  115.     if (!appDefaultsFileInstalled)
  116.         fprintf(stderr, 
  117.                 "Warning: the Stars app-defaults file is not installed\n");
  118.     XtMainLoop();
  119. }
  120.  
  121. initsky()
  122. {
  123.     register i;
  124.     static int revinit;
  125.  
  126.     newpos = (xy_t *)malloc(sizeof(xy_t));
  127.     initstars = (xy_t *)malloc((maxstars+1)*sizeof(xy_t));
  128.     stars = (xy_t *)malloc((maxstars+1)*sizeof(xy_t));
  129.     starcolor = (int *)malloc((maxstars+1)*sizeof(int));
  130.     dist = (int *)malloc((maxstars+1)*sizeof(int));
  131.     velocity.x = xinitialv;
  132.     velocity.y = yinitialv;
  133.     srand(getpid());
  134.     revinit=0;
  135.     if (reverse) {
  136.         revinit=1;
  137.         reverse = (!reverse);
  138.     }
  139.     for (i=0;i<maxstars;i++) {
  140.         if (rand() % PROBFAR)
  141.             initstars[i].v = (rand() % MAXVEL) + 1;
  142.         else
  143.             initstars[i].v = 0;
  144.         newstar(i);
  145.     }
  146.     if (revinit)
  147.         reverse = (!reverse);
  148. }
  149.  
  150. Boolean
  151. mvstars(w, data, call_data)
  152. Widget    w;
  153. struct image_data    *data[];
  154. XmDrawingAreaCallbackStruct    *call_data;
  155. {
  156.     register i;
  157.     extern xy_t *mv_line();
  158.  
  159.     for (i=0;i<maxstars;i++) {
  160.         if ((warp) && (initstars[i].u))
  161.              sendpoint(BlackPixel(dpy,XDefaultScreen(dpy)), stars[i]);
  162.         mv_line(initstars[i], midpt, dist[i], newpos);
  163.         stars[i].x = newpos[0].x;
  164.         stars[i].y = newpos[0].y;
  165.         if (reverse) {
  166.             dist[i] += initstars[i].u;
  167.             if ((dist[i] > ABS(midpt.x-initstars[i].x)) &&
  168.                 (dist[i] > ABS(midpt.y-initstars[i].y)))
  169.                 newstar(i);
  170.         }
  171.         else {
  172.             dist[i] -= initstars[i].u;
  173.         }
  174.         if ((stars[i].x >= width) || (stars[i].y >= height) ||
  175.             (stars[i].x < 0) || (stars[i].y < 0))
  176.                 newstar(i);
  177.         sendpoint(starcolor[i], stars[i]);
  178.         if (initstars[i].u == 0)
  179.             if ((rand() % PROBNEAR) == 1)
  180.                 initstars[i].u = (rand() % MAXVEL) + 1;
  181.     }
  182.     if (warp && showit)
  183.         sendpoint(BlackPixel(dpy,XDefaultScreen(dpy)), midpt);
  184.     if (turn)
  185.         turnmidpt();
  186.     if (numgen++ == distance)
  187.         exit(0);
  188.     midpt.x += velocity.x;
  189.     midpt.y += velocity.y;
  190.     if (midpt.x >= width) {
  191.         midpt.x = width;; 
  192.         velocity.x *= -1;
  193.     }
  194.     if (midpt.x <= 0) {
  195.         midpt.x = 0; 
  196.         velocity.x *= -1;
  197.     }
  198.     if (midpt.y >= height) {
  199.         midpt.y = height;
  200.         velocity.y *= -1;
  201.     }
  202.     if (midpt.y <= 0) {
  203.         midpt.y = 0;
  204.         velocity.y *= -1;
  205.     }
  206.     if (showit)
  207.         sendpoint(WhitePixel(dpy,XDefaultScreen(dpy)), midpt);
  208.     return FALSE;
  209. }
  210.  
  211. init_data()
  212. {
  213.     static int i;
  214.  
  215.     for (i=0; i<MAXCOLOR; i++) {
  216.         if((Data[i]=(struct image_data *)malloc(sizeof(struct image_data)))==
  217.                         NULL) {
  218.             fprintf(stderr,"Error malloc'ing Data[%d].\n",i);
  219.             exit(-1);
  220.         }
  221.         Data[i]->ncolors = XDisplayCells(dpy, XDefaultScreen(dpy));
  222.         Data[i]->width = 0;
  223.         Data[i]->height = 0;
  224.     }
  225.     numcolors = Min(Data[0]->ncolors, MAXCOLOR) - 1;
  226. }
  227.  
  228. init_canvas()
  229. {
  230.     Arg wargs[4];
  231.     XGCValues gcv;
  232.     XmString label;
  233.     static int i;
  234.  
  235.     /*
  236.      * Set the size of the drawing areas.
  237.      */
  238.     if (!width)
  239.         width = MIN_WIDTH;
  240.     if (!height)
  241.         height = MIN_HEIGHT;
  242.     XtSetArg(wargs[0], XtNwidth, width);
  243.     XtSetArg(wargs[1], XtNheight, height);
  244.     XtSetValues(framework, wargs,2);
  245.     /*
  246.      * create default, writable, graphics contexts for the canvas.
  247.      */
  248.     for (i=0; i<numcolors; i++) {
  249.         Data[i]->gc = XCreateGC(dpy, DefaultRootWindow(dpy), 
  250.                     0, (XGCValues *)NULL); 
  251.         Data[i]->width = width;
  252.         Data[i]->height = height;
  253.         /* set the background to black */
  254.         XSetBackground(dpy,Data[i]->gc,BlackPixel(dpy,XDefaultScreen(dpy)));
  255.         /* set the foreground of the ith context to i */
  256.         XSetForeground(dpy, Data[i]->gc, i);
  257.     }
  258.     /* label the buttons correctly */
  259.     if (reverse) {
  260.         label = XmStringCreate("REVERSE",XmSTRING_DEFAULT_CHARSET);
  261.         XtSetArg(wargs[0], XmNlabelString, label);
  262.         XtSetValues(button[1], wargs, 1);
  263.     }
  264.     else {
  265.         label = XmStringCreate("FORWARD",XmSTRING_DEFAULT_CHARSET);
  266.         XtSetArg(wargs[0], XmNlabelString, label);
  267.         XtSetValues(button[1], wargs, 1);
  268.     }
  269.     if (warp) {
  270.         label = XmStringCreate("IMPULSE ON",XmSTRING_DEFAULT_CHARSET);
  271.         XtSetArg(wargs[0], XmNlabelString, label);
  272.         XtSetValues(button[3], wargs, 1);
  273.     }
  274.     else {
  275.         label = XmStringCreate("WARP ON",XmSTRING_DEFAULT_CHARSET);
  276.         XtSetArg(wargs[0], XmNlabelString, label);
  277.         XtSetValues(button[3], wargs, 1);
  278.     }
  279.     /* zero the point buffer */
  280.     init_buffer();
  281. }
  282.  
  283. void 
  284. resize(w, data, call_data)
  285. Widget         w;
  286. struct image_data    *data[];
  287. caddr_t        call_data;
  288. {
  289.     static int i;
  290.     Arg wargs[10];
  291.     /*  
  292.      *   Get the new window size.
  293.      */   
  294.     for (i=0;i<numcolors;i++) {
  295.         XtSetArg(wargs[0], XtNwidth,  &Data[i]->width);
  296.         XtSetArg(wargs[1], XtNheight, &Data[i]->height);
  297.         XtGetValues(w, wargs, 2);
  298.     }
  299.     /*
  300.      * Clear the window.
  301.      */
  302.      if(XtIsRealized(canvas))
  303.              XClearArea(dpy, XtWindow(canvas), 0, 0, 0, 0, TRUE);
  304.     /* reset the buffers containing the lines, circles, boxes, etc. */
  305.     init_buffer();
  306.     /* recalculate offsets */
  307.     width = Data[0]->width; height = Data[0]->height;
  308.     midpt.x = x_center = width / 2;
  309.     midpt.y = y_center = height / 2;
  310.     for (i=0;i<maxstars;i++)
  311.         newstar(i);
  312. }
  313.  
  314. parseargs(ac, av)
  315. int ac;
  316. char **av;
  317. {
  318.     register int c;
  319.     extern int optind;
  320.     extern char *optarg;
  321.  
  322.     while ((c = getopt(ac, av, "AMFSXfruwB:W:H:c:a:b:D:n:x:y:")) != EOF) {
  323.         switch (c) {
  324.         case 'B':    bindex=atoi(optarg); 
  325.                 if ((bindex > NUMSIZ) || (bindex < 0))
  326.                     usage();
  327.                 break;
  328.         case 'M':    randcol--; break;
  329.         case 'F':    FullScreen=1; break;
  330.         case 'H':    height=atoi(optarg); break;
  331.         case 'S':    showit++; break;
  332.         case 'W':    width=atoi(optarg); break;
  333.         case 'X':    turn++; break;
  334.         case 'f':    NoShowButtons=1; break;
  335.         case 'r':    reverse++; break;
  336.         case 'w':    warp--; break;
  337.         case 'c':    icflag=0; initcolor=atoi(optarg); break;
  338.         case 'a':    xinitialv=atoi(optarg); break;
  339.         case 'b':    yinitialv=atoi(optarg); break;
  340.         case 'D':    distance=atoi(optarg); break;
  341.         case 'n':    maxstars=atoi(optarg); break;
  342.         case 'x':    midpt.x=atoi(optarg); xflag=0; break;
  343.         case 'y':    midpt.y=atoi(optarg); yflag=0; break;
  344.         case 'u':
  345.         case '?':    usage(); break;
  346.         }
  347.     }
  348. }
  349.  
  350. usage()
  351. {
  352.     fprintf(stderr,"stars [-AMXruw][-B[0123]][-a#][-b#][-c#][-d#][-x xmid][-y ymid][-H#][-W#]\n");
  353.     fprintf(stderr,"\tWhere: -M indicates use monochrome\n");
  354.     fprintf(stderr,"\t       -S indicates show midpt\n");
  355.     fprintf(stderr,"\t       -X indicates randomly walk the midpt\n");
  356.     fprintf(stderr,"\t       -r indicates put the ship in reverse\n");
  357.     fprintf(stderr,"\t       -u displays this message\n");
  358.     fprintf(stderr,"\t       -w indicates put the ship in warp\n");
  359.     fprintf(stderr,"\t       -B# specifies the initial star size\n");
  360.     fprintf(stderr,"\t       -H# specifies the initial window height\n");
  361.     fprintf(stderr,"\t       -W# specifies the initial window width\n");
  362.     fprintf(stderr,"\t       -a# specifies the inital 'x' velocity\n");
  363.     fprintf(stderr,"\t       -b# specifies the inital 'y' velocity\n");
  364.     fprintf(stderr,"\t       -c# specifies the star color\n");
  365.     fprintf(stderr,"\t       -d# specifies the duration of display\n");
  366.     fprintf(stderr,"\tDuring display :\n");
  367.     fprintf(stderr,"\t  [hjklHJKL] rogue-like control of midpt movement\n");
  368.     fprintf(stderr,"\t        '.' stops the motion of the midpt\n");
  369.     fprintf(stderr,"\t        '+' resets the midpt to screen center\n");
  370.     fprintf(stderr,"\t  '>'or '<' increases/decreases the delay (text mode)\n");
  371.     fprintf(stderr,"\t     b or B selects star size\n");
  372.     fprintf(stderr,"\t     c or C toggles all/one color (graphics mode only)");
  373.     fprintf(stderr,"\n\t     t or T toggles random walk of midpt\n");
  374.     fprintf(stderr,"\t     x or X clears the screen\n");
  375.     fprintf(stderr,"\t     r or R toggles reverse/forward\n");
  376.     fprintf(stderr,"\t     s or S toggles midpt display\n");
  377.     fprintf(stderr,"\t     w or W toggles warp/normal\n");
  378.     fprintf(stderr,"\t     q or Q exits\n");
  379.     exit(1);
  380. }
  381.  
  382. init_buffer()
  383. {
  384.     int i;
  385.  
  386.     for(i=0;i<MAXCOLOR;i++) {
  387.         Points.npoints[i] = 0;
  388.     }
  389. }
  390.  
  391. buffer_bit(color, x , y)
  392. int         color, x,y;
  393. {
  394.     static int i;
  395.  
  396.     if(Points.npoints[color] == MAXPOINTS - 1){
  397.       /*
  398.        * If the buffer is full, set the foreground color
  399.        * of the graphics context and draw the points in the window.
  400.        */
  401.         for (i=0; i<=numcolors; i++) {
  402.           if (Points.npoints[i]) {
  403.               XDrawPoints (dpy, XtWindow(canvas), Data[i]->gc, 
  404.                            Points.coord[i], Points.npoints[i], CoordModeOrigin);
  405.               /*
  406.                * Reset the buffer.
  407.                */
  408.               Points.npoints[i] = 0;
  409.           }
  410.         }
  411.     }
  412.     /*
  413.      * Store the point in the buffer according to its color.
  414.      */
  415.     Points.coord[color][Points.npoints[color]].x = x;
  416.     Points.coord[color][Points.npoints[color]].y = y;
  417.     Points.npoints[color]++;
  418. }
  419.  
  420. void
  421. start_iterate(w, cv, call_data)
  422. Widget w, cv;
  423. XmAnyCallbackStruct *call_data;
  424. {
  425.     XmString label;
  426.     Arg wargs[1];
  427.  
  428.     if(work_proc_id) {
  429.         XtRemoveWorkProc(work_proc_id);
  430.         work_proc_id = (XtWorkProcId)NULL; 
  431.         if (warp) {
  432.           label = XmStringCreate("RESUME IMPULSE",XmSTRING_DEFAULT_CHARSET);
  433.           XtSetArg(wargs[0], XmNlabelString, label);
  434.           XtSetValues(button[0], wargs, 1);
  435.         }
  436.         else {
  437.           label = XmStringCreate("RESUME WARP",XmSTRING_DEFAULT_CHARSET);
  438.           XtSetArg(wargs[0], XmNlabelString, label);
  439.           XtSetValues(button[0], wargs, 1);
  440.         }
  441.         label = XmStringCreate("ENGINES OFF",XmSTRING_DEFAULT_CHARSET);
  442.         XtSetArg(wargs[0], XmNlabelString, label);
  443.         XtSetValues(button[3], wargs, 1);
  444.     }
  445.     else {
  446.         /*
  447.          * Register mvstars() as a WorkProc.
  448.          */
  449.         work_proc_id = XtAddWorkProc(mvstars, cv);
  450.         label = XmStringCreate("STOP",XmSTRING_DEFAULT_CHARSET);
  451.         XtSetArg(wargs[0], XmNlabelString, label);
  452.         XtSetValues(button[0], wargs, 1);
  453.         if (warp) {
  454.           label = XmStringCreate("IMPULSE ON",XmSTRING_DEFAULT_CHARSET);
  455.           XtSetArg(wargs[0], XmNlabelString, label);
  456.           XtSetValues(button[3], wargs, 1);
  457.         }
  458.         else {
  459.           label = XmStringCreate("WARP ON",XmSTRING_DEFAULT_CHARSET);
  460.           XtSetArg(wargs[0], XmNlabelString, label);
  461.           XtSetValues(button[3], wargs, 1);
  462.         }
  463.     }
  464. }
  465.  
  466. void 
  467. stop_iterate(w, cv, call_data)
  468. Widget                w, cv;
  469. XmAnyCallbackStruct  *call_data;
  470. {
  471.     XmString label;
  472.     Arg wargs[1];
  473.  
  474.     reverse = (!reverse);
  475.     if (reverse) {
  476.         label = XmStringCreate("REVERSE",XmSTRING_DEFAULT_CHARSET);
  477.         XtSetArg(wargs[0], XmNlabelString, label);
  478.         XtSetValues(button[1], wargs, 1);
  479.     }
  480.     else {
  481.         label = XmStringCreate("FORWARD",XmSTRING_DEFAULT_CHARSET);
  482.         XtSetArg(wargs[0], XmNlabelString, label);
  483.         XtSetValues(button[1], wargs, 1);
  484.     }
  485. }
  486.  
  487. void
  488. Warp(w, call_value)
  489. Widget w;
  490. XmAnyCallbackStruct *call_value;
  491. {
  492.     XmString label;
  493.     Arg wargs[1];
  494.  
  495.     warp = (!warp);
  496.     if (warp) {
  497.         Clear();
  498.           if (work_proc_id) {
  499.         label = XmStringCreate("IMPULSE ON",XmSTRING_DEFAULT_CHARSET);
  500.         XtSetArg(wargs[0], XmNlabelString, label);
  501.         XtSetValues(button[3], wargs, 1);
  502.           }
  503.           else {
  504.             label=XmStringCreate("ENGINES OFF",XmSTRING_DEFAULT_CHARSET);
  505.         XtSetArg(wargs[0], XmNlabelString, label);
  506.         XtSetValues(button[3], wargs, 1);
  507.         label=XmStringCreate("RESUME IMPULSE",XmSTRING_DEFAULT_CHARSET);
  508.         XtSetArg(wargs[0], XmNlabelString, label);
  509.         XtSetValues(button[0], wargs, 1);
  510.           }
  511.     }
  512.     else {
  513.         if (work_proc_id) {
  514.         label = XmStringCreate("WARP ON",XmSTRING_DEFAULT_CHARSET);
  515.         XtSetArg(wargs[0], XmNlabelString, label);
  516.         XtSetValues(button[3], wargs, 1);
  517.         }
  518.         else {
  519.         label=XmStringCreate("ENGINES OFF",XmSTRING_DEFAULT_CHARSET);
  520.         XtSetArg(wargs[0], XmNlabelString, label);
  521.         XtSetValues(button[0], wargs, 1);
  522.         label=XmStringCreate("RESUME WARP",XmSTRING_DEFAULT_CHARSET);
  523.         XtSetArg(wargs[0], XmNlabelString, label);
  524.         XtSetValues(button[0], wargs, 1);
  525.         }
  526.     }
  527. }
  528.  
  529. void
  530. quit(w, call_value)
  531. Widget w;
  532. XmAnyCallbackStruct *call_value;
  533. {
  534.     exit(0);
  535. }
  536.  
  537. turnmidpt()
  538. {
  539.  
  540.     if (rand() % 2)
  541.         midpt.x++;
  542.     else
  543.         midpt.x--;
  544.     if (rand() % 2)
  545.         midpt.y++;
  546.     else
  547.         midpt.y--;
  548.     if (midpt.x >= width-1)
  549.         midpt.x = width - 2; 
  550.     if (midpt.x <= 1)
  551.         midpt.x = 2; 
  552.     if (midpt.y >= height-1)
  553.         midpt.y = height - 2;
  554.     if (midpt.y <= 1)
  555.         midpt.y = 2;
  556. }
  557.  
  558. XtEventHandler
  559. Getkey(w, client_data, event)
  560. Widget w;
  561. caddr_t client_data;
  562. XKeyEvent *event;
  563. {
  564.     Arg wargs[1];
  565.     static int i;
  566.  
  567.     switch (XLookupKeysym(event, 0)) {
  568.     case XK_h: velocity.x--; break;
  569.     case XK_j: velocity.y--; break;
  570.     case XK_k: velocity.y++; break;
  571.     case XK_l: velocity.x++; break;
  572.     case XK_H: velocity.x -= VEL_INC; break;
  573.     case XK_J: velocity.y -= VEL_INC; break;
  574.     case XK_K: velocity.y += VEL_INC; break;
  575.     case XK_L: velocity.x += VEL_INC; break;
  576.     case XK_plus:
  577.     case XK_equal: midpt.x = width/2; midpt.y = height/2; Clear();
  578.     case XK_period: velocity.x = velocity.y = 0; break;
  579.     case XK_B: bindex=0; 
  580.           Clear();
  581.           break;
  582.     case XK_b: ++bindex; bindex=bindex % (NUMSIZ+1);
  583.           Clear(); break;
  584.     case XK_f:
  585.     case XK_F: NoShowButtons = (!NoShowButtons);
  586.            if (NoShowButtons) {
  587.             for (i=0;i<4;i++)
  588.                 XtUnrealizeWidget(button[i]);
  589.             XtSetArg(wargs[0], XmNbottomPosition, &bottom);
  590.             XtGetValues(canvas, wargs, 1);
  591.             XtSetArg(wargs[0], XmNbottomPosition, 99);
  592.             XtSetValues(canvas, wargs, 1);
  593.            }
  594.            else {
  595.             XtSetArg(wargs[0], XmNbottomPosition, bottom);
  596.             XtSetValues(canvas, wargs, 1);
  597.             for (i=0;i<4;i++) {
  598.                 XtManageChild(button[i]);
  599.                 XtRealizeWidget(button[i]);
  600.             }
  601.            }
  602.            break;
  603.     case XK_C:
  604.     case XK_c: randcol = (!randcol); break;
  605.     case XK_r:
  606.     case XK_R: reverse = (!reverse); break;
  607.     case XK_s:
  608.     case XK_S: showit = (!showit); break;
  609.     case XK_t:
  610.     case XK_T: turn = (!turn); break;
  611.     case XK_X:
  612.     case XK_x: Clear(); break;
  613.     case XK_w:
  614.     case XK_W: warp = (!warp); 
  615.            if (warp)
  616.             Clear();
  617.            break;
  618.     case XK_q:
  619.     case XK_Q: exit(0); break;
  620.     default:  break;
  621.     }
  622. }
  623.  
  624. /* a star is born
  625.  */
  626. newstar(i)
  627. {
  628.     if (reverse) {
  629.         if (rand() % 2) {
  630.             initstars[i].y = stars[i].y= rand()%(height-1);
  631.             if (rand() % 2)
  632.                 initstars[i].x = stars[i].x=1;
  633.             else
  634.                 initstars[i].x = stars[i].x=width-1;
  635.         }
  636.         else {
  637.             initstars[i].x = stars[i].x= rand()%(width-1);
  638.             if (rand() % 2)
  639.                 initstars[i].y = stars[i].y=1;
  640.             else
  641.                 initstars[i].y = stars[i].y=height-1;
  642.         }
  643.     }
  644.     else {
  645.         initstars[i].y = stars[i].y= rand()%(height-1);
  646.         initstars[i].x = stars[i].x= rand()%(width-1);
  647.     }
  648.     if (randcol)
  649.         starcolor[i] = (rand() % (numcolors-2)) + 2;
  650.     else
  651.         starcolor[i] = initcolor;
  652.     dist[i] = 0;
  653.     initstars[i].u = initstars[i].v;
  654. }
  655.  
  656. xy_t points[NUMSIZ][16] = {
  657. /* ptsize[0] */    { {-1,-1},{1,-1},{-1,1},{1,1},{0,0},{0,0},{0,0},{0,0},
  658.         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0} },
  659. /* ptsize[1] */    { {0,-3},{-2,-2},{0,-2},{2,-2},{-1,-1},{0,-1},{1,-1},{-1,1},
  660.         {0,1},{1,1},{-2,2},{0,2},{2,2},{0,3},{0,0},{0,0} },
  661. /* ptsize[2] */    { {0,-3},{0,-2},{-1,-1},{0,-1},{1,-1},{-2,0},{-1,0},{1,0},
  662.         {2,0},{-1,1},{0,1},{1,1},{0,2},{0,3},{0,0},{0,0} },
  663. /* ptsize[3] */    { {-4,-4},{0,-4},{4,-4},{-2,-2},{0,-2},{2,-2},{0,-6},{0,8},
  664.         {0,-8},{0,6},{-2,2},{0,2},{2,2},{-4,4},{0,4},{4,4} }
  665. };
  666.  
  667. int ptsize[NUMSIZ] = { 4, 14, 14, 16 };
  668.  
  669. sendpoint(color, point)
  670. int color;
  671. xy_t point;
  672. {
  673.     static int i;
  674.     xy_t newp;
  675.  
  676.     if (bindex) {
  677.         for (i=0; i < ptsize[bindex-1]; i++) {
  678.             newp.x = point.x + points[bindex-1][i].x;
  679.             newp.y = point.y + points[bindex-1][i].y;
  680.             if (newp.x >= width) newp.x = width-1;
  681.             if (newp.x < 0) newp.x = 0;
  682.             if (newp.y >= height) newp.y = height-1;
  683.             if (newp.y < 0) newp.y = 0;
  684.             buffer_bit(color, newp.x, newp.y);
  685.         }
  686.         buffer_bit(color, point.x, point.y);
  687.     }
  688.     else
  689.         buffer_bit(color, point.x, point.y);
  690. }
  691.  
  692. Clear() {
  693.     static int i;
  694.  
  695.      if(XtIsRealized(canvas))
  696.          XClearArea(dpy, XtWindow(canvas), 0, 0, 0, 0, TRUE);
  697.     for (i=0; i<=numcolors; i++)
  698.           Points.npoints[i] = 0;
  699. }
  700.